
package com.rt.schedulenew.utils.netty.common;

import java.util.Arrays;
import java.util.HashMap;
import java.lang.reflect.Type;

import com.google.gson.reflect.TypeToken;
import com.google.gson.Gson;

import java.util.concurrent.ConcurrentHashMap;

import com.rt.schedulenew.utils.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;

import java.util.List;

import com.corundumstudio.socketio.SocketIOClient;

import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.springframework.util.CollectionUtils;

public class NettyConstants {
    private static Logger logger;
    public static String KEY_PRE = "";
    public static String PRE = "_";
    public static Map<String, Map<String, SocketIOClient>> clientMap;
    public static Map<String, String> sessionKeyMap;
    public static Map<String, List<String>> userSessionIdKeyMap;

    static {
        logger = LoggerFactory.getLogger(NettyConstants.class);
        NettyConstants.clientMap = new ConcurrentHashMap<>();
        NettyConstants.sessionKeyMap = new ConcurrentHashMap<String, String>();
        NettyConstants.userSessionIdKeyMap = new ConcurrentHashMap<String, List<String>>();
    }

    public static class WebSocketConnectParam {
        public static class Param {
            public static String USER_LOGIN;

            static {
                Param.USER_LOGIN = "userLogin";
            }
        }
    }

    public static class WebSocketAction {
        public static int SOCKET_CONNECT = 1;
        public static int SOMEONE_QUIT = 10;
        public static String WebSocketResult;

        public static String getFormatWebSocketResult(int type, String jsonData) {
            String json = "";
            try {
                json = String.format(WebSocketAction.WebSocketResult, type, jsonData);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage(), e);
            }
            return json;
        }

        public static WebSocketActionResult toWebSocketActionResult(String msg) {
            WebSocketActionResult result = null;
            try {
                Gson gson = new Gson();
                Type type = new TypeToken<WebSocketActionResult>() {
                }.getType();
                result = (WebSocketActionResult) gson.fromJson(msg, type);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

        static {
            WebSocketAction.WebSocketResult = "{code: %d, data: '%s'}";
        }

        public static class WebSocketActionResult {
            private int code;
            private String data;

            public int getCode() {
                return this.code;
            }

            public void setCode(int code) {
                this.code = code;
            }

            public String getData() {
                return this.data;
            }

            public void setData(String data) {
                this.data = data;
            }

            public WebSocketActionResult(String jsonResultStr) {
                WebSocketActionResult jsonResult = JsonUtil.toBean(jsonResultStr, WebSocketActionResult.class);
                this.code = jsonResult.getCode();
                this.data = jsonResult.getData();
            }
        }
    }

    public enum ClientType {
        WEB("WEB_", "PC_WEB端消息客户端前缀"),
        H5("H5_", "手机H5端消息客户端前缀"),
        ANDROID("ANDROID_", "安卓原生端消息客户端前缀"),
        IOS("IOS_", "IOS原生端消息客户端前缀"),
        WXX("WXX_", "微信小程序消息客户端前缀"),
        PAD("PAD_", "PAD端消息客户端前缀"),
        TV("TV_", "电视端消息客户端前缀"),
        C("C_", "C端消息客户端前缀");

        public final String key;
        public final String value;

        ClientType(String key, String value) {
            this.key = key;
            this.value = value;
        }

        public static ClientType get(String key) {
            return Arrays.stream(values()).filter(x -> x.key.equals(key))
                    .findFirst().orElse(null);
        }
    }

    public static class WebSocketClients {
        public static Map<String, String> getParams(String paramUrl) {
            Map<String, String> map = new HashMap<String, String>();
            try {
                if (paramUrl != null) {
                    String[] paramArr = paramUrl.split("&");
                    List<String> paramsStrList = Arrays.stream(paramArr).filter(StringUtils::isNotBlank)
                            .collect(Collectors.toList());

                    if (!CollectionUtils.isEmpty(paramsStrList)) {
                        for (String param : paramsStrList) {
                            String[] keyValueArr = param.split("=");
                            if (keyValueArr.length >= 2) {
                                map.put(keyValueArr[0], keyValueArr[1]);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return map;
        }

        public static String getDefaultKey(String userId) {
            return "" + userId;
        }

        public static String getClientType(String userKey) {
            userKey = userKey.replace("", "");
            if (userKey.contains("_")) {
                userKey = userKey.substring(0, userKey.indexOf("_"));
            }
            return userKey;
        }

        public static Map<String, String> getUserInfo(String userKey) {
            Map<String, String> map = new HashMap<String, String>();
            String clientTypeName = getClientType(userKey);
            map.put("sourceType", clientTypeName);
            String userId = getUser(userKey);
            if (userId.contains("_")) {
                clientTypeName = userId.substring(userId.indexOf("_") + 1);
                userId = userId.substring(0, userId.indexOf("_"));
            }
            map.put("userId", userId);
            map.put("clientTypeName", clientTypeName);
            return map;
        }

        public static void add(String userKey, SocketIOClient client) {
            Map<String, String> param = getUserInfo(userKey);
            String clientTypeName = param.get("clientTypeName");
            String userId = param.get("userId");
            Map<String, SocketIOClient> map = NettyConstants.clientMap.get(userId);
            if (map == null) {
                map = new HashMap<String, SocketIOClient>();
            }
            map.put(clientTypeName, client);
            NettyConstants.clientMap.put(userId, map);
        }

        public static SocketIOClient get(String userKey) {
            Map<String, String> param = getUserInfo(userKey);
            String clientTypeName = param.get("clientTypeName");
            String userId = param.get("userId");
            Map<String, SocketIOClient> map = NettyConstants.clientMap.get(userId);
            SocketIOClient client = null;
            if (map != null) {
                client = map.get(clientTypeName);
            }
            return client;
        }

        public static void remove(String userKey) {
            Map<String, String> param = getUserInfo(userKey);
            String clientTypeName = param.get("clientTypeName");
            String userId = param.get("userId");
            Map<String, SocketIOClient> map = NettyConstants.clientMap.get(userId);
            if (map != null) {
                map.remove(clientTypeName);
            }
        }

        public static String getUser(String userKey) {
            return userKey.replace("", "").replace(ClientType.WEB.key, "").replace(ClientType.H5.key, "").replace(ClientType.ANDROID.key, "").replace(ClientType.IOS.key, "").replace(ClientType.WXX.key, "").replace(ClientType.PAD.key, "").replace(ClientType.TV.key, "").replace(ClientType.C.key, "");
        }

        public static boolean hasConnection(String userId) {
            return NettyConstants.clientMap.containsKey(userId);
        }

        public static boolean hasConnectionByKey(String userKey) {
            Map<String, String> param = getUserInfo(userKey);
            return NettyConstants.clientMap.containsKey(param.get("userId"));
        }
    }
}
